﻿
/*
 * Javasript based on Functions(JBF) 1.03
 * 
 * Copyright(c) 2010, Fooxee (JA86.CN)
 *
 * JBF is licensed under the terms of the Open Source GPL 3.0(http://www.gnu.org/licenses/gpl.html) license. 
 * 
 * JBF's blog: http://www.cnblogs.com/JBF/
 * 
 * Created by Fooxee. at 2010.03.08  mailTo:hjccjun@163.com
 */

/**
 * JBF的底层Ajax实现方法.
 * 
 * <pre></pre>
 * @参数 {Object} Ajax配置项
 * <li>url			{String} 发送请求的地址。</li>
 * <li>method		{String} (默认: "GET") 请求方式 ("POST" 或 "GET")， 默认为 "GET"。</li>
 * <li>async		{Boolean} (默认: true) 默认设置下，所有请求均为异步请求。如果需要发送同步请求，请将此选项设置为 false。注意，同步请求将锁住浏览器，用户其它操作必须等待请求完成才可以执行。</li>
 * <li>cache		{Boolean} (默认: true) 设置为 false 将不会从浏览器缓存中加载请求信息。</li>
 * <li>beforeSend	{Function} 发送请求前可修改 XMLHttpRequest 对象的函数，如添加自定义 HTTP 头。XMLHttpRequest对象是唯一的参数。</li>
 * <li>callback		{Function} 请求成功后回调函数。这个方法有两个参数：服务器返回数据、XMLHttpRequest对象
	function (data, XMLHttpRequest)
	{
		//TODO
	}
	</li>
 * <li>complete		{Function} 请求完成后回调函数 (请求成功或失败时均调用)。参数： XMLHttpRequest对象，返回状态
 	function (XMLHttpRequest,status)
	{
		//TODO
	}
	</li>
 * <li>error		{Function} 请求失败时将调用此方法。这个方法有三个参数：返回状态,状态文本,XMLHttpRequest对象。
 	function (status,statusText,XMLHttpRequest)
	{
		//TODO
	}
	</li>
 * <li>params	{Object} 发送到服务器的数据。必须为 Key/Value 格式。</li>
 * <li></li>
 * @返回 {Boolean}
 */
JBF.Ajax=JBF.ajax=function(options)
{
	options=options?options:{};
	
	//请求方式
	options.method=(options.method=='GET' || options.method=='POST')?options.method:'GET';
	//是否异步请求
	options.async=(options.async===true || options.async===false)?options.async:true;
	//是否缓存
	options.cache=(options.cache===true || options.cache===false)?options.cache:false;
	
	//回调方法
	options.callback=JBF.isFun(options.callback)?options.callback:JBF.emptyFn;
	//请求发送前
	options.beforeSend=JBF.isFun(options.beforeSend)?options.beforeSend:JBF.emptyFn;
	//请求完成后
	options.complete=JBF.isFun(options.complete)?options.complete:JBF.emptyFn;
	//请求错误时
	options.error=JBF.isFun(options.error)?options.error:JBF.emptyFn;
	
	//请求参数
	options.params=JBF.isObj(options.params)?options.params:null;
	
	if(!options.cache)
	{
		options.params.timespace=new Date().getTime();
	}
	
	//构造参数
	var PostParams=function()
	{
		var tempArr = new Array();
		JBF.each(options.params,function(p,idx)
		{
			tempArr.push(p + "=" + options.params[p]);
		});
		return tempArr.join("&");
	}();
	
	if(options.method=='GET')
	{
		if(options.url.indexOf('?')>3)
		{
			options.url +='&'+PostParams;
		}
		else
		{
			options.url +='?'+PostParams;
		}
	}
	
	var httpRequest=(function()
	{
        try {return new ActiveXObject("Microsoft.XMLHTTP");}
        catch(e) {try {return new ActiveXObject("Msxml2.XMLHTTP");}
        catch(e) {try {return new XMLHttpRequest();}catch(e) {return window.createRequest();};};};
	})();
	var pollHandler;
	var stateChgHandler=function()
	{
		if(httpRequest.readyState==4)
		{
			if(httpRequest.status==200)
			{
				options.callback(httpRequest.responseText||httpRequest.responseXml,httpRequest);
			}
			else //http 状态错误 返回 状态,状态文本,request对象
			{
				options.error(httpRequest.status,httpRequest.statusText,httpRequest);
			}
			options.complete(httpRequest.status,httpRequest);
			clearTimeout(pollHandler);
		}
	};
	
	//httpRequest.setRequestHeader("Content-Type","text/xml"); 
	options.beforeSend(httpRequest);
	httpRequest.open(options.method,options.url,options.async);
	//ie
	if(!+"\v1")
	{
		httpRequest.onreadystatechange=stateChgHandler;
	}
	if(PostParams)
	{
        httpRequest.setRequestHeader("Content-Length", PostParams.length);   
        httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded;");
    };
	httpRequest.send(options.method=='GET'?null:PostParams);
	
	//ff
	if(!!+"\v1")
	{
		httpRequest.onreadystatechange=stateChgHandler();
		//异步为真时
		if(options.async)
		{
			pollHandler=setTimeout(function()
			{
				stateChgHandler();
			},0);
		}
	}
	
	
};
JBF.apply(JBF.Ajax,{
	
	/**
	 * POST方式来进行Ajax请求
	 * @参数 {String} 发送请求的地址。
	 * @参数 {Object} 发送到服务器的数据。必须为 Key/Value 格式。
	 * @参数 {Function} 请求成功后回调函数。这个方法有两个参数：服务器返回数据、XMLHttpRequest对象
	 * @参数 {Boolean} (默认: true) 默认设置下，所有请求均为异步请求。如果需要发送同步请求，请将此选项设置为 false。注意，同步请求将锁住浏览器，用户其它操作必须等待请求完成才可以执行。
	 * @参数 {Boolean} (默认: true) 设置为 false 将不会从浏览器缓存中加载请求信息。
	 * @返回 {Void}
	 */
	post:function(url,params,callback,async,cache)
	{
		return 	JBF.Ajax({url:url,params:params,callback:callback,method:'POST',async:async,cache:cache});
	},
	/**
	 * GET方式来进行Ajax请求
	 * @参数 {String} 发送请求的地址。
	 * @参数 {Object} 发送到服务器的数据。必须为 Key/Value 格式。
	 * @参数 {Function} 请求成功后回调函数。这个方法有两个参数：服务器返回数据、XMLHttpRequest对象
	 * @参数 {Boolean} (默认: true) 默认设置下，所有请求均为异步请求。如果需要发送同步请求，请将此选项设置为 false。注意，同步请求将锁住浏览器，用户其它操作必须等待请求完成才可以执行。
	 * @参数 {Boolean} (默认: true) 设置为 false 将不会从浏览器缓存中加载请求信息。
	 * @返回 {Void}
	 */
	get:function(url,params,callback,async,cache)
	{
		return 	JBF.Ajax({url:url,params:params,callback:callback,method:'GET',async:async,cache:cache});
	},
	/**
	 * POST方式来进行Ajax请求,并对返回数据进行JSON反序列操作，如果失败侧返回原数据。
	 * @参数 {String} 发送请求的地址。
	 * @参数 {Object} 发送到服务器的数据。必须为 Key/Value 格式。
	 * @参数 {Function} 请求成功后回调函数。这个方法有两个参数：服务器返回数据、XMLHttpRequest对象
	 * @参数 {Boolean} (默认: true) 默认设置下，所有请求均为异步请求。如果需要发送同步请求，请将此选项设置为 false。注意，同步请求将锁住浏览器，用户其它操作必须等待请求完成才可以执行。
	 * @参数 {Boolean} (默认: true) 设置为 false 将不会从浏览器缓存中加载请求信息。
	 * @返回 {Void}
	 */
	postJSON:function(url,params,callback,async,cache)
	{
		this.post(url,params,function(rspText,httpRequest)
		{
			try
			{
				callback(JBF.stringToJson(rspText),httpRequest);
			}
			catch(e)
			{
				callback(rspText,httpRequest);	
			}
		},async);
	},
	/**
	 * GET方式来进行Ajax请求,并对返回数据进行JSON反序列操作，如果失败侧返回原数据。
	 * @参数 {String} 发送请求的地址。
	 * @参数 {Object} 发送到服务器的数据。必须为 Key/Value 格式。
	 * @参数 {Function} 请求成功后回调函数。这个方法有两个参数：服务器返回数据、XMLHttpRequest对象
	 * @参数 {Boolean} (默认: true) 默认设置下，所有请求均为异步请求。如果需要发送同步请求，请将此选项设置为 false。注意，同步请求将锁住浏览器，用户其它操作必须等待请求完成才可以执行。
	 * @参数 {Boolean} (默认: true) 设置为 false 将不会从浏览器缓存中加载请求信息。
	 * @返回 {Void}
	 */
	getJSON:function(url,params,callback,async,cache)
	{
		this.get(url,params,function(rspText,httpRequest)
		{
			try
			{
				callback(JBF.stringToJson(rspText),httpRequest);
			}
			catch(e)
			{
				callback(rspText,httpRequest);	
			}
		},async);
	}
});